package com.cheems.cn.server;

import com.cheems.cn.RpcApplication;
import com.cheems.cn.mdoel.RpcRequest;
import com.cheems.cn.mdoel.RpcResponse;
import com.cheems.cn.registry.LocalRegistry;
import com.cheems.cn.serializer.JdkSerializer;
import com.cheems.cn.serializer.Serializer;
import com.cheems.cn.serializer.SerializerFactory;
import io.vertx.core.Handler;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpServerResponse;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.lang.reflect.Method;

/**
 * @author JTB
 */
@Slf4j
public class httpServerHandler implements Handler<HttpServerRequest> {
    @Override
    public void handle(HttpServerRequest request) {

        // 指定序列化器
        final Serializer serializer = SerializerFactory.getInstance(RpcApplication.getRpcConfig().getSerializer());

        //记录日志
        log.info("接收请求：{}", request.method() + " " +request.uri());

        //异步处理请求
        request.bodyHandler(body -> {
            byte[] bytes = body.getBytes();
            RpcRequest rpcRequest = null;
            try {
                rpcRequest = serializer.deserialize(bytes, RpcRequest.class);
            }catch (Exception e){
                e.printStackTrace();
            }

            //构造响应结果对象
            RpcResponse rpcResponse = new RpcResponse();
            if (rpcRequest == null){
                rpcResponse.setMessage("请求参数为空");
                doResponse(request, rpcResponse,serializer);
                return;
            }

            try {
                //获取需要调用的服务实现类,通过反射调用实现类
                Class<?> implClass = LocalRegistry.get(rpcRequest.getServiceName());
                //获取需要调用的方法的方法名和参数列表
                Method method = implClass.getMethod(rpcRequest.getMethodName(), rpcRequest.getParameterTypes());
                //反射调用方法获取结果
                Object result = method.invoke(implClass.newInstance(), rpcRequest.getArgs());

                //封装返回结果
                rpcResponse.setData(result);
                rpcResponse.setDataType(method.getReturnType());
                rpcResponse.setMessage("ok");
            }catch (Exception e){
                e.printStackTrace();
                rpcResponse.setMessage(e.getMessage());
                rpcResponse.setException(e);
            }

            //响应
            doResponse(request,rpcResponse,serializer);
        });


    }

    /**
     * 响应结果
     * @param request
     * @param rpcResponse
     * @param serializer
     */
    private void doResponse(HttpServerRequest request, RpcResponse rpcResponse, Serializer serializer) {
        HttpServerResponse httpServerResponse = request.response().putHeader("Content-Type", "application/json");

        try {
            //序列化结果
            byte[] serialized = serializer.serialize(rpcResponse);
            httpServerResponse.end(Buffer.buffer(serialized));
        }catch (IOException e){
            e.printStackTrace();
            httpServerResponse.end(Buffer.buffer());
        }
    }
}
